<?php
/**
 * Note: *
 */
namespace App\Services;

class IpService
{

    /**
     * 将每ip的1和2，3和4,5和6，7和8位对换
     * @param $num1
     * @return float|int
     */
    private function swap($num1)
    {
        $tmp1 = $num1;
        $tmp2 = 255;
        $str = "";
        $arr = [];
        while (($tmp1 != 0 && $tmp2 != 0) or ($tmp1 == 0 && $tmp2 != 0) or ($tmp2 == 0 && $tmp1 != 0)) {
            $s1 = $tmp1 % 2;
            $str = $s1 . $str;
            $tmp1 = intval($tmp1 / 2);
            $tmp2 = intval($tmp2 / 2);
        }
        for ($i = 0; $i < strlen($str); $i++) {
            $arr[$i] = substr($str, $i, 1);
        }
        $tmp1 = $arr[0];
        $arr[0] = $arr[1];
        $arr[1] = $tmp1;

        $tmp1 = $arr[2];
        $arr[2] = $arr[3];
        $arr[3] = $tmp1;

        $tmp1 = $arr[4];
        $arr[4] = $arr[5];
        $arr[5] = $tmp1;

        $tmp1 = $arr[6];
        $arr[6] = $arr[7];
        $arr[7] = $tmp1;

        $str = "";
        foreach ($arr as $v) {
            $str .= $v;
        }
        return bindec($str);
    }

    /**
     * 和秘钥异或
     * @param $num1
     * @param $num2
     * @return float|int
     */
    private function xord($num1, $num2)
    {
        $tmp1 = $num1;
        $tmp2 = hexdec($num2);
        $str = "";
        while (($tmp1 != 0 && $tmp2 != 0) or ($tmp1 == 0 && $tmp2 != 0) or ($tmp2 == 0 && $tmp1 != 0)) {
            $s1 = $tmp1 % 2;
            $s2 = $tmp2 % 2;
            if ($s1 == $s2) {
                $str = "0" . $str;
            } else {
                $str = "1" . $str;
            }
            $tmp1 = intval($tmp1 / 2);
            $tmp2 = intval($tmp2 / 2);
        }
        return bindec($str);
    }
    /**
     * IP 加密
     * @param string $ip
     * @return string
     */
    private function encrypt(string $ip): string
    {
        $port = '';
        if (strpos($ip, ':') !== false) list($ip, $port) = explode(':', $ip);

        $Pkey = "0x88";
        $testIp = $ip;
        $resultStrList = array();
        $result = "";
        $swapNum = "";
        $resultStrList = explode(".", $testIp);
        foreach ($resultStrList as $key => $val) {
            $swapNum = $this->swap($val);
            if ($key == 0) {
                $result .= $this->xord($swapNum, $Pkey);
            } else {
                $result .= "." . $this->xord($swapNum, $Pkey);
            }
        }
        return $port ? $result.':'.$port : $result;
    }

    /**
     * 解密
     * @param $ipStr
     * @return string
     */
    private function decrypt($ipStr): string
    {
        $Pkey = "0x88";
        $testIp = $ipStr;
        $resultStrList = array();
        $result = "";
        $swapNum = "";
        $resultStrList = explode(".", $testIp);
        foreach ($resultStrList as $key => $val) {
            $decryptNum = $this->xord($val, $Pkey);
            $swapNum = $this->swap($decryptNum);
            if ($key == 0) {
                $result .= $swapNum;
            } else {
                $result .= "." . $swapNum;
            }
        }
        return $result;
    }

    /**
     * 魔术方法
     * @param $method
     * @param $arg
     * @return mixed
     * @throws \Exception
     */
    public static function __callStatic($method, $arg)
    {
        $class = new static;
        if (!method_exists($class, $method)) {
            throw new \Exception('method is not found');
        }
        return (new static)->{$method}(...$arg);
    }
}
